// Copyright 2022 Huawei Cloud Computing Technology Co., Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

import work from 'webworkify-webpack';
import logger from './Logger';
const Logger = logger;
import getEvents from './tools/event';
import Util from './Util';
import BaseClass from './tools/baseClass';
import WebGLRenderer from './WebglRenderer';
import { CLOUD_PHONE_RATIO } from './config/commonConfig';
import global from '../config/global';

class CanvasPlayer extends BaseClass {
  constructor(options) {
    super(options);
    this.options = { ...options };
    this.moduleInit = false;
    this.streamList = [];
    this.document = document;
    this.tinyH264Worker = null;
    this.videoStreamId = 1;
    this.util = new Util();

    this.options.events = getEvents();
    this.setCanvas();
    this.setImagerPlayer();

    //将本行代码放主线程执行
    this.tinyH264Worker = work(require.resolve('./codec/Decode.js'));
    this.tinyH264Worker.addEventListener('message', e => {
      const message =
        /** @type {{type:string, width:number, height:number, data:ArrayBuffer, renderStateId:number}} */ e.data;
      switch (message.type) {
        case 'pictureReady':
          const { width, height, data } = message;
          self.postMessage({
            type: 'decoded',
            data: {
              data,
              width,
              height,
            },
          });
          this.onRenderImage({
            data,
            width,
            height,
          });
          break;
        case 'decoderReady':
          this.moduleInit = true;
          break;
      }
    });
  }

  setCanvas() {
    const $canvas = this.util.createCanvas(
      this.options.isMobile,
      CLOUD_PHONE_RATIO,
      this.options.containerId,
    );
    // 放入元素内部
    let parentNode = document.getElementById(this.options.containerId);
    parentNode.appendChild($canvas);
    this.canvas = $canvas;
  }

  setImagerPlayer() {
    const canvas = document.getElementById('playCanvas');
    this.webglPlayer = new WebGLRenderer(canvas, {
      preserveDrawingBuffer: false,
    });
  }

  onRenderImage(obj) {
    let unData = new Uint8Array(obj.data);
    let width = obj.width;
    let height = obj.height;
    let yLength = width * height;
    let uvLength = (width / 2) * (height / 2);
    if (!this.webglPlayer) {
      this.setImagerPlayer();
    }
    this.webglPlayer.renderFrame(unData, width, height, yLength, uvLength);
  }

  startDecod() {
    const streamData = this.streamList.shift();
    if (streamData && streamData.buffer) {
      this.tinyH264Worker.postMessage(
        {
          type: 'decode',
          data: streamData.buffer,
          offset: streamData.byteOffset,
          length: streamData.byteLength,
          renderStateId: this.videoStreamId,
        },
        [streamData.buffer],
      );
    } else {
      Logger.error('startDecode', 'data is null', 'data:', data);
    }
  }

  decode(data) {
    if (global.__IS_DEBUG__) {
      let traceId = window.delayAnalysis.shiftTraceId('receive') || '';
      window.delayAnalysis.cacheTraceId('decode', traceId);
      window.delayAnalysis.record(['decode', 'start', traceId]);
    }

    // 暂存流数据，等解码器准备好后开始解码
    this.streamList.push(data);
    if (this.moduleInit) {
      this.startDecod();
    }
  }

  destroy() {
    this.tinyH264Worker.postMessage({
      type: 'release',
      renderStateId: this.videoStreamId,
    });
    this.tinyH264Worker.terminate();
  }
}

export default CanvasPlayer;
